const utils = require('./utils');
const Sequelize = require('sequelize');

// const debug = require('debug')('core:db/database');

// 缓存数据库实例 instances
const cachedInstances = {};

/**
 * @class DataBase
 * 数据库连接池封装，基于sequelize
 * @constructor
 * @param {String} dbType  mysql|mssql
 * @param {Object} options options配置内容
 */
class DataBase {
  constructor(dbType, options) {
    if (!options) {
      throw new Error(`不存在数据库配置：${dbType}的配置！`);
    }
    this._config = options;
    this._databaseInstances = [];
    this.dbType = dbType;
    cachedInstances[dbType] = {};
    this.init();
  }

  get databases() {
    return this._databaseInstances;
  }

  get config() {
    return this._config;
  }

  /**
   * @function init
   * @description 初始化创建数据库实例
   */
  init() {
    for (let k of Object.keys(this.config.clients)) {
      // const config = this.config.clients[k];
      const config = this._parseConfig(k);
      if (config.database && config.init_connect) {
        // 指明了database才默认初始化连接
        this._databaseInstances.push(k);
      }
    }
    this.databases.forEach(database => {
      this.createClient(database);
    });

  }

  /**
   * @function createClient 创建Db Client
   * @param {String} name 数据库名称
   */
  createClient(name) {

    let options = this._parseConfig(name);
    if (!options || !options.database) {
      console.error('参数database不存在或者未指名数据库：%s %o', name, options);
      return;
    }
    const {
      database,
      user,
      password
    } = options;
    let sequelize = new Sequelize(database, user, password, options);
    sequelize
      .authenticate()
      .then(() => {
        console.log('数据库：%s 已经连接成功~', database);
      }).catch(err => {
        console.error('无法连接到数据库：%s, 错误：%o', database, err);
      });

    cachedInstances[this.dbType][database] = sequelize;
    return sequelize;
  }

  /**
   * @example use('key')、use('key.database')
   *    key 表示直接使用config key配置连接
   *    key.database 表示使用key配置+database数据库连接
   * @param {String} database 数据库名称
   * @return {Object} Sequelize db 连接
   *
   */
  use(database) {
    let db = cachedInstances[this.dbType][database];
    if (!db) {
      // 不存在则动态创建数据库连接
      db = this.createClient(database);
    }
    return db;
  }

  /**
   * @function _parseConfig 解析配置
   * @param {String} database
   */
  _parseConfig(database) {

    if (!database) {
      return null;
    }

    // db
    let db = database,
      dbName = null;

    // support (instance.name) or (instance)
    if (database.indexOf('.') !== -1) {
      let arrs = database.split('.');
      db = arrs[0];
      dbName = arrs[1];
    };

    let config = utils.getClientConfig(this.config, db);
    if (dbName) {
      config.database = dbName; // 此情况说明指名了instance.database
    }
    return config;
  }

  /**
   * @function closeAll 释放所有数据库连接池
   * @retrun {Promise} 返回关闭的数据库promise
   */
  closeAll() {
    let closeConns = [];
    for (let key in cachedInstances[this.dbType]) {
      closeConns.push(cachedInstances[this.dbType][key].close());
      cachedInstances[this.dbType][key] = null;
    }
    return Promise.all(closeConns);
  }

};

module.exports = DataBase;
